package com.pi.tcp.handler;

import java.net.SocketAddress;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.ChannelHandler.Sharable;

import com.pi.tcp.util.PiBedInsEnum;
import com.pi.base.enumerate.redis.RedisCacheEnum;
import com.pi.base.util.cache.RedisUtil;
import com.pi.base.util.lang.ByteUtil;
import com.pi.comm.sequence.SnowflakeFactory;
import com.pi.smart.client.ins.comm.domain.BaseWifiCmd;

@Sharable
public class WifiLockHander extends ChannelHandlerAdapter {

    private static Logger logger = LoggerFactory.getLogger(WifiLockHander.class);

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object baseMsg) throws Exception {
        SocketAddress remoteAddress = (null != ctx.channel()) ? ctx.channel().remoteAddress() : null;
        if (null == baseMsg) {
            return;
        }
        if (baseMsg instanceof DatagramPacket) {
            DatagramPacket packet = (DatagramPacket) baseMsg;
            logger.info("接收到未知的UDP数据: {}", packet.content());
        } else if (baseMsg instanceof ByteBuf) {
            ByteBuf message = (ByteBuf) baseMsg;
            byte[] bytes = new byte[message.readableBytes()];
            message.readBytes(bytes);
            logger.info("原始数据：{}", ByteUtil.byteToHex(bytes));
            byte insType = bytes[11];
            String deviceCode;
            if ((bytes[0] & 0xFF) == 0xAA && (insType & 0xFF) == 0xC1) {
                byte[] devCode = new byte[7];
                byte[] cmdCode = new byte[6];

                System.arraycopy(bytes, 4, devCode, 0, 7);
                System.arraycopy(bytes, 11, cmdCode, 0, cmdCode.length);
                deviceCode = ByteUtil.byteToHex(devCode, false);

                BaseWifiCmd cmdMessage = new BaseWifiCmd();
                cmdMessage.setCmd(cmdCode);
                cmdMessage.setDevCode(deviceCode.toUpperCase());
                cmdMessage.setMessageId(SnowflakeFactory.getDefaultWorker().nextId());
                cmdMessage.setTs(System.currentTimeMillis());
                RedisUtil.rpush(RedisCacheEnum.SMART_DEVICELOCK_WIFI, cmdMessage);
                logger.info("[msg_send] {}", cmdMessage);


                byte[] res = new byte[6];
                res[0] = 0x55;
                res[1] = 0x20;
                res[2] = 0x00;
                res[3] = 0x01;
                res[4] = insType;

                if (bytes[12] == 0x03 && bytes[13] == 0x3c) {
                    //查询有没有远程开门记录
                    String remote =
                            RedisUtil.get(RedisCacheEnum.SMART_LOCK_REMOTE_UNLOCK, deviceCode);
                    if (StringUtils.isNotBlank(remote)) {
                        res[5] = (byte) 0x00;
                        RedisUtil.del(RedisCacheEnum.SMART_LOCK_REMOTE_UNLOCK, deviceCode);
                    } else {
                        res[5] = (byte) 0x01;
                    }
                } else {
                    res[5] = (byte) 0x00;
                }
                logger.info("[code_response] {}", ByteUtil.byteToHex(res));
                ctx.writeAndFlush(Unpooled.copiedBuffer(res));
            }
            if ((bytes[0] & 0xFF) == 0xAA && (insType & 0xFF) == 0xF3) {
                logger.info("时间同步：{}", ByteUtil.byteToHex(bytes));
                byte[] res = new byte[14];
                res[0] = 0x55;
                res[1] = 0x20;
                res[2] = 0x00;
                res[3] = 0x0E;

                res[4] = (byte) 0xF3;
                res[5] = 0x00;
                res[6] = 0x00;
                res[7] = 0x00;
                res[8] = 0x00;
                res[9] = 0x00;

                long time = System.currentTimeMillis() / 1000;
                res[10] = (byte) (time >> 24);
                res[11] = (byte) (time >> 16);
                res[12] = (byte) (time >> 8);
                res[13] = (byte) time;
                ctx.writeAndFlush(Unpooled.copiedBuffer(res));
            }
            if ((bytes[0] & 0xFF) == 0xAA && (insType & 0xFF) == 0xF4) {
                byte[] devCode = new byte[7];

                byte[] cmdCode = new byte[6];

                System.arraycopy(bytes, 4, devCode, 0, 7);

                deviceCode = ByteUtil.byteToHex(devCode, false);

                cmdCode[0] = (byte) 0xC1;
                cmdCode[1] = (byte) 0x04;
                cmdCode[2] = (byte) 0x07;
                int length = (bytes[12] * 256 + bytes[13]) / 3;
                for (int k = 0; k < length; k++) {
                    cmdCode[3] = (byte) bytes[14 + (k * 3)];
                    cmdCode[4] = (byte) bytes[15 + (k * 3)];
                    cmdCode[5] = (byte) bytes[16 + (k * 3)];
                    BaseWifiCmd cmdMessage = new BaseWifiCmd();
                    cmdMessage.setCmd(cmdCode);
                    cmdMessage.setDevCode(deviceCode);
                    cmdMessage.setMessageId(SnowflakeFactory.getDefaultWorker().nextId());
                    cmdMessage.setTs(System.currentTimeMillis());
                    RedisUtil.rpush(RedisCacheEnum.SMART_DEVICELOCK_WIFI, cmdMessage);
                    logger.info("[msg_send] {}", cmdMessage);
                }


                byte[] res = new byte[6];
                res[0] = 0x55;
                res[1] = 0x20;
                res[2] = 0x00;
                res[3] = 0x01;
                res[4] = (byte) 0xF4;
                res[5] = 0x00;
            } else {
                logger.error("接收参数错误,当前接收到的数据类型为-{},接收到的端口为：{}", baseMsg.getClass().getName(),
                        (null != remoteAddress) ? remoteAddress.toString() : "");
            }
            logger.debug("释放连接 - {}", (null != remoteAddress) ? remoteAddress.toString() : "");
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        ctx.close();
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
//		ctx.flush();
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
//	  ctx.close();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        String message = null != cause.getMessage() ? cause.getMessage() : "";
        // String localMsg = cause.getLocalizedMessage();
        Channel channel = ctx.channel();
        // SocketAddress local = channel.localAddress();
        SocketAddress remote = channel.remoteAddress();
        // ChannelMetadata metadata = channel.metadata();
        if (message.indexOf("Connection timed out") >= 0 || message.indexOf("Connection reset") >= 0
                || "远程主机强迫关闭了一个现有的连接。".equals(message)) {
            logger.error("远程主机-{}-断开了连接", remote);
            // 尝试清空channel
            channel.flush();
            // 当错误发生时，尝试调用垃圾回收, 不知道是否可以减少Direct Memory 泄露的错误,需要验证
//      System.gc();
        } else {
            logger.error(cause.getMessage(), cause);
        }
        ctx.close();
    }

    public static void main(String[] args) {
        logger.info("发送wifi指令： {}", ByteUtil.byteToHex(PiBedInsEnum.generateWifiIns("PI", "piaidianzi", "")));
    }
}
